package huu.phong.googlemusic;

import huu.phong.googlemusic.model.Song;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Authenticator;
import java.net.MalformedURLException;
import java.net.PasswordAuthentication;
import java.util.ArrayDeque;
import java.util.List;
import java.util.Queue;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;

import javazoom.jl.decoder.JavaLayerException;

public class GoogleMusic extends JFrame {
	private static final long serialVersionUID = 1L;
	private JList songs;
	private DefaultListModel modelSongs;
	private JList albums;
	private DefaultListModel modelAlbums;
	private JComboBox repeats, sorts;
	private JButton search;
	private JTextField value;
	private JFileChooser chooser;
	private MediaPlayer mediaPlayer;
	private Toolkit toolkit = Toolkit.getDefaultToolkit();
	private Clipboard clipboard = toolkit.getSystemClipboard();
	private Runtime runtime = Runtime.getRuntime();
	private JMenuBar menuBar;
	private JMenuItem itemUpdateSong, itemLogin, itemSaveMP3;
	JMenuItem itemSaveCurrentSong;
	private JMenuItem itemUndo;
	private JMenuItem itemRedo;
	private JMenuItem itemSetProxy;
	private JMenu menuSetup, menuMedia;
	private JMenuItem mediaPlay, mediaNext, mediaPrevious;
	private ButtonGroup group;
	private ProxySelector dialogProxy;
	private Configure configure;
	private Class<?> object = this.getClass();
	private ColorSlider slider;
	JLabel startDuration;
	JLabel endDuration;
	private JLabel info;
	JLabel songInfo;
	private JLabel labelSearch;
	private JLabel iconStatus;
	private JPopupMenu popupMenu;
	private History<List<Song>> history;
	private Dimension dimension;
	private Login login;
	private MusicManager googleMusic;
	
	public GoogleMusic() {
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setSize(1020, 700);
//		setResizable(false);
		setIconImage(toolkit.getImage(object.getResource("/images/zing.png")));
		configure = Configure.load();
		mediaPlayer = new MediaPlayer(GoogleMusic.this, configure);
		history = new History<List<Song>>();
		addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent arg0) {
				configure.save();
			}
		});
		addComponentListener(new ComponentAdapter() {
			public void componentMoved(ComponentEvent e) {
				configure.location = getLocation();
			}
		});
		
//		Add menu bar
		menuBar = new JMenuBar();
		menuSetup = new JMenu("Setup");
		menuSetup.add(itemSetProxy = new JMenuItem("Set proxy..."));
		itemSetProxy.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				if (dialogProxy == null) dialogProxy = new ProxySelector();
				Point point = getLocation();
				point.x += 200;
				point.y += 100;
				dialogProxy.setHost(configure.host);
				dialogProxy.setPort(configure.port);
				dialogProxy.setUsername(configure.username);
				dialogProxy.setPassword(configure.password);
				dialogProxy.setSystemProxy(configure.systemProxy);
				dialogProxy.setUseProxy(configure.useProxy);
				dialogProxy.setLocation(point);
				dialogProxy.setVisible(true);
			}
		});
//		menuBar.add(menuFile);
		menuBar.add(initMenuAction());
		menuBar.add(menuSetup);
		menuBar.add(initMenuMedia());
		menuBar.add(Box.createHorizontalGlue());
		menuBar.add(mediaPrevious = new JMenu());
		mediaPrevious.setIcon(getImage("previous.png"));
		mediaPrevious.addMouseMotionListener(new MouseMotionAdapter() {
			public void mouseMoved(MouseEvent arg0) {
				mediaPrevious.setSelected(false);
			}
		});
		mediaPrevious.addMouseListener(new MouseAdapter() {
			public void mousePressed(MouseEvent arg0) {
				mediaPrevious.setSelected(false);
				new Thread(){
					public void run(){
						try {
							mediaPlayer.previous();
						} catch (MalformedURLException e) {
							e.printStackTrace();
						} catch (IOException e) {
							e.printStackTrace();
						} catch (JavaLayerException e) {
							e.printStackTrace();
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
				}.start();
			}
		});
		menuBar.add(mediaPlay = new JMenu());
		mediaPlay.setIcon(getImage("play.png"));
		mediaPlay.addMouseMotionListener(new MouseMotionAdapter() {
			public void mouseMoved(MouseEvent arg0) {
				mediaPlay.setSelected(false);
			}
		});
		mediaPlay.addMouseListener(new MouseAdapter() {
			public void mousePressed(MouseEvent arg0) {
				mediaPlay.setSelected(false);
				if (mediaPlayer.playing){
					mediaPlay.setIcon(getImage("play.png"));
					mediaPlayer.pause();
				}else if(mediaPlayer.paused){
					mediaPlay.setIcon(getImage("play.png"));
					new Thread(){
						public void run(){
							mediaPlayer.resumeSong();
						}
					}.start();
				}else{
					play();
				}
			}
		});
		menuBar.add(mediaNext = new JMenu());
		mediaNext.setIcon(getImage("next.png"));
		mediaNext.addMouseMotionListener(new MouseMotionAdapter() {
			public void mouseMoved(MouseEvent arg0) {
				mediaNext.setSelected(false);
			}
		});
		mediaNext.addMouseListener(new MouseAdapter() {
			public void mousePressed(MouseEvent arg0) {
				mediaNext.setSelected(false);
				new Thread(){
					public void run(){
						try {
							mediaPlayer.next();
						} catch (MalformedURLException e) {
							e.printStackTrace();
						} catch (IOException e) {
							e.printStackTrace();
						} catch (JavaLayerException e) {
							e.printStackTrace();
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
				}.start();
			}
		});
		dimension = menuBar.getPreferredSize();
		dimension.height = 25;
		menuBar.setPreferredSize(dimension);
		final JPanel panelSlider = new JPanel();
		panelSlider.addMouseMotionListener(new MouseAdapter() {
			public void mouseMoved(MouseEvent arg0) {
				panelSlider.setFocusCycleRoot(false);
				panelSlider.setFocusable(false);
			}
		});
		dimension = panelSlider.getPreferredSize();
		dimension.height = 25;
		dimension.width = 298;
		panelSlider.setPreferredSize(dimension);
		panelSlider.setBorder(BorderFactory.createMatteBorder(0, 1, 0, 0, new Color(204, 204, 204)));
		panelSlider.setLayout(new BoxLayout(panelSlider, BoxLayout.LINE_AXIS));
		panelSlider.setOpaque(false);
		panelSlider.add(startDuration = new JLabel("00:00", JLabel.RIGHT));
//		startDuration.setOpaque(true);
		dimension = new Dimension(34, 25);
		startDuration.setPreferredSize(dimension);
		startDuration.setSize(dimension);
		startDuration.setMaximumSize(dimension);
		startDuration.setMinimumSize(dimension);
		slider = new ColorSlider(mediaPlayer, configure);
		panelSlider.add(Box.createRigidArea(new Dimension(5, 25)));
		panelSlider.add(slider);
		panelSlider.add(Box.createRigidArea(new Dimension(5, 25)));
		panelSlider.add(endDuration = new JLabel("00:00", JLabel.LEFT));
		endDuration.setPreferredSize(dimension);
		endDuration.setSize(dimension);
		endDuration.setMaximumSize(dimension);
		endDuration.setMinimumSize(dimension);
		menuBar.add(panelSlider);
		setJMenuBar(menuBar);
		
		chooser = new JFileChooser();
		dialogProxy = new ProxySelector();
		dialogProxy.setMain(GoogleMusic.this);
		dialogProxy.setConfigure(configure);
		Container container = getContentPane();
		container.setLayout(new BorderLayout());
		container.add(initPanelSearch(), BorderLayout.NORTH);
		popupMenu = new JPopupMenu();
		JMenuItem itemCopy = new JMenuItem("Copy direct links");
		itemCopy.setIcon(getImage("copy.png"));
		JMenuItem itemSaveLinks = new JMenuItem("Save direct links (*.m3u8)...");
		itemSaveLinks.setIcon(getImage("save.png"));
		JMenuItem itemSaveAsPlaylist = new JMenuItem("Save direct links (*.m3u)...");
		itemSaveAsPlaylist.setIcon(getImage("m3u.png"));
		itemSaveAsPlaylist.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				saveAsPlaylist();
			}
		});
		itemSaveLinks.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				saveLinks();
			}
		});
		itemCopy.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				new Thread(){
					public void run(){
						int[] save = songs.getSelectedIndices();
						String saveString = "";
						for (int i = 0; i < save.length; i++){
							saveString += configure.songs.get(save[i]).getDirectLink() + "\n";
						}
						clipboard.setContents(new StringSelection(saveString), null);
					}
				}.start();
			}
		});
		JMenuItem itemRename = new JMenuItem("Rename title");
		itemRename.setIcon(getImage("rename.png"));
		itemRename.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				if (songs.getSelectedIndex() == -1) return;
				String title = JOptionPane.showInputDialog(GoogleMusic.this, "Enter title for song", configure.songs.get(songs.getSelectedIndex()).getTitle());
				if (title != null){
					configure.songs.get(songs.getSelectedIndex()).setTitle(title);
					setSongs(configure.songs, true);
				}
			}
		});
		JMenuItem itemDelete = new JMenuItem("Delete", getImage("delete.png"));
		itemDelete.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				
			}
		});
		itemSaveMP3 = new JMenuItem("Save songs (*.mp3)", getImage("save.png"));
		itemSaveMP3.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				saveFiles();
			}
		});
		popupMenu.add(itemCopy);
		popupMenu.add(itemSaveLinks);
		popupMenu.add(itemSaveAsPlaylist);
		popupMenu.add(itemRename);
		popupMenu.addSeparator();
		popupMenu.add(itemSaveMP3);
		
		JPanel panelList = new JPanel(new GridLayout(1, 2, 5, 0));
		panelList.add(new JScrollPane(songs = new JList(modelSongs = new DefaultListModel()),
				JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
				JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED));
		songs.setCellRenderer(new SongListRenderer());
//		songs.addMouseMotionListener(new MouseMotionAdapter() {
//			public void mouseMoved(MouseEvent e){
//				int index = songs.locationToIndex(e.getPoint());
//				if (index < 0) return;
//				Song song = configure.songs.get(index);
//				songs.setToolTipText(song.getSongInfo());
//			}
//		});
		songs.addKeyListener(new KeyAdapter() {
			@Override
			public void keyPressed(KeyEvent arg0) {
				if (arg0.getKeyCode() == KeyEvent.VK_ENTER) {
					play();
				}
			}
		});
		songs.setFixedCellHeight(25);
		songs.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent e) {
				if (SwingUtilities.isRightMouseButton(e)) {
					if (songs.getSelectedIndices().length <= 1){
						if (configure.songs.isEmpty()){
							songs.clearSelection();
						}else{
							songs.setSelectedIndex(songs.locationToIndex(e.getPoint()));
						}
					}
					popupMenu.show(songs, e.getX(), e.getY());
				}
				if (e.getClickCount() == 2) {
					play();			
				}
			}
		});
		panelList.add(new JScrollPane(albums = new JList(modelAlbums = new DefaultListModel()),
				JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
				JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED));
		albums.setCellRenderer(new AlbumListRenderer());
		albums.setFixedCellHeight(130);
		albums.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent e){
				if (modelAlbums.isEmpty()) return;
				if (e.getClickCount() == 2){
					setSongs(googleMusic.currentAlbums.get(albums.getSelectedIndex()).songs, true);
				}
			}
		});
		albums.addKeyListener(new KeyAdapter() {
			public void keyPressed(KeyEvent e){
				if (e.getKeyCode() == KeyEvent.VK_ENTER) {
					setSongs(googleMusic.currentAlbums.get(albums.getSelectedIndex()).songs, true);
				}
			}
		});
		container.add(panelList, BorderLayout.CENTER);
		
		JMenuBar status = new JMenuBar();
		dimension = status.getPreferredSize();
		dimension.height = 140;
		status.setPreferredSize(dimension);
		status.setLayout(new BorderLayout());
		JPanel leftStatus = new JPanel();
		leftStatus.setOpaque(false);
		leftStatus.setLayout(new BoxLayout(leftStatus, BoxLayout.X_AXIS));
		leftStatus.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0));
//		leftStatus.add(Box.createRigidArea(new Dimension(5, 0)));
		leftStatus.add(iconStatus = new JLabel(getImage("searching.gif")));
		iconStatus.setVisible(false);
		iconStatus.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5));
		leftStatus.add(songInfo = new JLabel(configure.status));
		status.add(leftStatus, BorderLayout.CENTER);
		
//		JPanel panelActive = new JPanel();
//		panelActive.setPreferredSize(new Dimension(200, 25));
//		panelActive.add(info = new JLabel("[" + configure.title + "]", JLabel.CENTER));
//		info.setPreferredSize(new Dimension(155, 14));
//		panelActive.setBorder(BorderFactory.createMatteBorder(0, 1, 0, 0, new Color(204, 204, 204)));
//		panelActive.setOpaque(false);
//		status.add(panelActive, BorderLayout.EAST);
		container.add(status, BorderLayout.SOUTH);
		container.add(Box.createRigidArea(new Dimension(5, 0)), BorderLayout.EAST);
		container.add(Box.createRigidArea(new Dimension(5, 0)), BorderLayout.WEST);
		if (configure.location == null){
			setLocationRelativeTo(null);
		}else{
			setLocation(configure.location);
		}
		setTitle(configure.title);
		setVisible(true);
		//Load configure;
		loadConfigure();
		googleMusic = new MusicManager();
		if (!configure.autoLogin || configure.googleUsername.equals("")){
			loginToGoogleMusic();
		}else if (configure.autoLogin){
			setIconStatus(true);
	        songInfo.setText("Login to Goolge Music");
			new Thread(){
				public void run(){
					googleMusic.login(configure.googleUsername, configure.googlePassword);
					if (!googleMusic.logged){
						JOptionPane.showMessageDialog(GoogleMusic.this, "Wrong email or password.", "Login", JOptionPane.INFORMATION_MESSAGE);
						loginToGoogleMusic();
						setIconStatus(false);
						songInfo.setText(configure.title);
						return;
					}
					songInfo.setText("Sorting song");
					googleMusic.songs = configure.allSong;
					googleMusic.init();
					setSongs(configure.songs, true);
					sorts.setSelectedItem(configure.sort);
					setIconStatus(false);
					songInfo.setText(configure.title);
				}
			}.start();
		}
		toolkit.getSystemEventQueue().push(new MyEventQueue());
	}
	
	private void loadConfigure(){
		repeats.setSelectedItem(configure.repeat);
		value.setText(configure.value);
		setProxy();
	}

	private void saveAsPlaylist() {
		final String str = showSave("Save as playlist", new File(configure.oldFolder), "Google Music.m3u");
		if (str == null) return;
		new Thread() {
			public void run() {
				try {
					List<Song> listSongs = configure.songs;
					BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(str),"UTF-8"));
					int[] lists = songs.getSelectedIndices();
					out.write("#EXTM3U");
					out.newLine();
					for (int i = 0; i < lists.length; i++) {
						Song song = listSongs.get(lists[i]);
						out.write("#EXTINF:-1," + song.getTitle());
						out.newLine();
						out.write(song.getDirectLink());
						out.newLine();
					}
					out.flush();
					out.close();
					JOptionPane.showMessageDialog(GoogleMusic.this, "Saved " + lists.length + " direct links to " + str, "Save as playlist", JOptionPane.INFORMATION_MESSAGE);
				} catch (Exception e1) {
					setTitle(e1.toString());
					e1.printStackTrace();
				}
			}
		}.start();
	}

	private void saveLinks() {
		final String str = showSave("Save songs", new File(configure.oldFolder), "Google Music.m3u8");
		if (str == null) return;
		new Thread() {
			public void run() {
				try {
					List<Song> listSongs = configure.songs;
					BufferedWriter out = new BufferedWriter(new FileWriter(str));
					int[] lists = songs.getSelectedIndices();
					for (int i = 0; i < lists.length; i++) {
						Song song = listSongs.get(lists[i]);
						out.write(song.getDirectLink());
						out.newLine();
					}
					out.flush();
					out.close();
					JOptionPane.showMessageDialog(GoogleMusic.this, "Saved " + lists.length + " direct links to " + str, "Save as m3u8", JOptionPane.INFORMATION_MESSAGE);
				} catch (Exception e1) {
					setTitle(e1.toString());
					e1.printStackTrace();
				}
			}
		}.start();
	}
	
	private void saveFiles() {
		chooser.setCurrentDirectory(new File(configure.oldFolder));
		chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
		int ret = chooser.showSaveDialog(GoogleMusic.this);
		if (ret != JFileChooser.APPROVE_OPTION) {
			return;
		}
		final String dir = chooser.getSelectedFile().getAbsolutePath();
		configure.oldFolder = dir;
		itemSaveMP3.setEnabled(false);
		new Thread() {
			public void run() {
				List<Song> listSongs = configure.songs;
				int i = 0;
				int[] lists = songs.getSelectedIndices();
				try {
					for (i = 0; i < lists.length; i++) {
						Song song = listSongs.get(lists[i]);
						info.setToolTipText("Saving file " + song.toString() + ".mp3 to " + dir);
						song.saveToFile(dir);
					}
					info.setToolTipText("");
					JOptionPane.showMessageDialog(GoogleMusic.this, "Saved " + i + " file to " + dir, "Save mp3 file", JOptionPane.INFORMATION_MESSAGE);
					itemSaveMP3.setEnabled(true);
				} catch (Exception e) {
					setTitle(e.toString());
					e.printStackTrace();
				}
			}
		}.start();
	}

	public void setSongs(final List<Song> lists, boolean clear) {
		configure.songs = lists;
		modelSongs.clear();
		history.add(lists);
		new Thread(){
			public void run(){
				Queue<Thread> threads = getThreadLoaders(lists, modelSongs);
				while(!threads.isEmpty()){
					Thread thread = threads.poll();
					thread.start();
					try {
						thread.join();
					} catch (Exception e) {
					}
				}
			}
		}.start();
		if (history.undo > 0){
			itemUndo.setEnabled(true);
		}else{
			itemUndo.setEnabled(false);
		}
		if (history.redo > 0){
			itemRedo.setEnabled(true);
		}else{
			itemRedo.setEnabled(false);
		}
	}
	
	private Queue<Thread> getThreadLoaders(final List<?> lists, final DefaultListModel model) {
		Queue<Thread> threads = new ArrayDeque<Thread>();
		int number = lists.size() / 20;
		if ((lists.size() % 20) != 0) number ++;
		for (int i = 0; i < number; i++){
			int index = i * 20;
			int end = index + 20;
			end = end > lists.size()? lists.size() : end;
			final List<?> songs = lists.subList(index, end);
			threads.add(new Thread(){
				public void run(){
					SwingUtilities.invokeLater(new Runnable() {
						@Override
						public void run() {
							for (Object song : songs) {
								model.addElement(song);
							}
						}
					});
				}
			});
		}
		return threads;
	}

	public void setAlbums(){
		new Thread(){
			public void run(){
				if (configure.sort.equals("Artist")){
					googleMusic.currentAlbums = googleMusic.artists;
				}else if (configure.sort.equals("Genre")){
					googleMusic.currentAlbums = googleMusic.genres;
				}else{
					googleMusic.currentAlbums = googleMusic.albums;
				}
				new Thread(){
					public void run(){
						Queue<Thread> threads = getThreadLoaders(googleMusic.currentAlbums, modelAlbums);
						while(!threads.isEmpty()){
							Thread thread = threads.poll();
							thread.start();
							try {
								thread.join();
							} catch (Exception e) {
							}
						}
					}
				}.start();
			}
		}.start();
	}
	
	private void search(){
		String valueSearch = value.getText().trim();
		if (valueSearch.equals("")) return;
		labelSearch.setIcon(getImage("searching.gif"));
		search.setEnabled(false);
		configure.value = valueSearch;
		new Thread(){
			public void run(){
				setSongs(googleMusic.search(configure.value), true);
				search.setEnabled(true);
				labelSearch.setIcon(getImage("search24.png"));
			}
		}.start();
	}

	private void play() {
		final int index = songs.getSelectedIndex();
		if (configure.songs.isEmpty() || index >= configure.songs.size()) return;
		new Thread(){
			public void run(){
				try {
					if (configure.defaultMediaPlayer == null || configure.defaultMediaPlayer.equals("")
							|| !(new File(configure.defaultMediaPlayer).exists())) {
						mediaPlayer.play(index);
					} else {
						Song song = configure.songs.get(index);
						setTitle("Sending: '" + song +"'...");
						runtime.exec(configure.defaultMediaPlayer + " " + song.getDirectLink());
						setTitle("Sended '" + song.getTitle() + "' - " + configure.title);
					}
				} catch (Exception e) {
					setTitle(e.toString());
					e.printStackTrace();
				}
			}
		}.start();
	}
	
	public void setCurrentSong(int index){
		songs.setSelectedIndex(index);
	}

	//Set proxy for application. Note restart application
	private void setProxy(String host, String port, final String username, final String password){
		if (configure.useProxy){
			if (configure.systemProxy){
				System.setProperty("java.net.useSystemProxies", "true");
			}else{
				System.setProperty("java.net.useSystemProxies", "false");
				System.setProperty("http.proxySet", "true");
				System.setProperty("http.proxyHost", host);
		        System.setProperty("http.proxyPort", port);
			}
			Authenticator.setDefault(new Authenticator() {
				protected PasswordAuthentication getPasswordAuthentication() {
			        return new PasswordAuthentication(username, password.toCharArray());
			    }
			});
		}else{
			System.setProperty("java.net.useSystemProxies", "false");
			System.setProperty("http.proxySet", "false");
			System.setProperty("http.proxyHost", "");
	        System.setProperty("http.proxyPort", "");
		}
	}
	
	public void setProxy(){
		setProxy(configure.host, configure.port, configure.username, configure.password);
	}
	
	private ImageIcon getImage(String name){
		return new ImageIcon(object.getResource("/images/" + name));
	}
	
	private JMenu initMenuAction(){
		JMenu menuAction = new JMenu("Action");
		itemUndo = new JMenuItem("Undo");
		itemUndo.setAccelerator(KeyStroke.getKeyStroke('Z', KeyEvent.CTRL_DOWN_MASK));
		itemUndo.setEnabled(false);
		itemUndo.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				setTitle("Undoing - " + configure.title);
				new Thread(){
					public void run(){
						if (history.undo()){
							setSongs(history.result, true);
							setTitle(configure.title);
						}
					}
				}.start();
			}
		});
		itemUndo.setIcon(getImage("undo.png"));
		menuAction.add(itemUndo);
		itemRedo = new JMenuItem("Redo");
		itemRedo.setAccelerator(KeyStroke.getKeyStroke('Y', KeyEvent.CTRL_DOWN_MASK));
		itemRedo.setEnabled(false);
		itemRedo.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				setTitle("Redoing - " + configure.title);
				new Thread(){
					public void run(){
						if (history.redo()){
							setSongs(history.result, true);
							setTitle(configure.title);
						}
					}
				}.start();
			}
		});
		itemRedo.setIcon(getImage("redo.png"));
		menuAction.add(itemRedo);
		menuAction.addSeparator();
		menuAction.add(itemLogin = new JMenuItem("Login..."));
		itemLogin.setIcon(getImage("login.png"));
		itemLogin.setAccelerator(KeyStroke.getKeyStroke('L', KeyEvent.CTRL_DOWN_MASK));
		itemLogin.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				loginToGoogleMusic();
			}
		});
		menuAction.add(itemUpdateSong = new JMenuItem("Update song"));
		itemUpdateSong.setIcon(getImage("refresh.png"));
		itemUpdateSong.setAccelerator(KeyStroke.getKeyStroke('U', KeyEvent.CTRL_DOWN_MASK));
		itemUpdateSong.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				if (googleMusic == null || !googleMusic.logged){
					JOptionPane.showMessageDialog(GoogleMusic.this, "You not logged. Please login by select Action>Login...", "Update song", JOptionPane.INFORMATION_MESSAGE);
					return;
				}
				new Thread(){
					public void run(){
						try {
							setIconStatus(true);
							songInfo.setText(" Updating song from Google Music");
							googleMusic.initSongs();
							googleMusic.init();
							setIconStatus(false);
							songInfo.setText("Updated song from Google Music");
						} catch (Exception e1) {
							e1.printStackTrace();
						}
					}
				}.start();
			}
		});
		menuAction.addSeparator();
		menuAction.add(itemSaveCurrentSong = new JMenuItem("Save current song", getImage("save.png")));
		itemSaveCurrentSong.setEnabled(false);
		itemSaveCurrentSong.setToolTipText("Current song can saved when completed buffer");
		itemSaveCurrentSong.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				new Thread(){
					public void run(){
						String file = showSave("Save current song", new File(configure.oldFolder), mediaPlayer.currentSong.toString() + ".mp3");
						if (file == null) return;
						if (mediaPlayer.bufferringFlag){
							JOptionPane.showInternalMessageDialog(GoogleMusic.this, "New song is buffering. Can't save now, wait to completed buffer", "Save current song", JOptionPane.INFORMATION_MESSAGE);
							return;
						}
						mediaPlayer.saveFile(file);
					}
				}.start();
			}
		});
		return menuAction;
	}
	
	public void loginToGoogleMusic() {
		if (login == null) login = new Login();
		login.setLocationRelativeTo(GoogleMusic.this);
		login.configure = configure;
		login.main = GoogleMusic.this;
		login.restore();
		login.googleMusic = googleMusic;
		login.setVisible(true);
	}

	private JPanel initPanelSearch(){
		JPanel panelSearch = new JPanel(new FlowLayout(0, 5, 5));
		panelSearch.add(Box.createRigidArea(new Dimension(1,0)));
		panelSearch.add(labelSearch = new JLabel(getImage("search24.png"), JLabel.CENTER));
		panelSearch.add(value = new JTextField(25));
		value.setToolTipText("<html><b>Search for</b><br/>Title or Artist or Album. Example : Quang Le<br/>Title - Artist. Example: Hai Ba Nam - Pham Truong<br/>Not case sensitive</html>");
		value.addKeyListener(new KeyAdapter() {
			@Override
			public void keyPressed(KeyEvent arg0) {
				if (arg0.getKeyCode() == KeyEvent.VK_ENTER) {
					search();
				}
			}
		});
		panelSearch.add(search = new JButton("Go"));
		search.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				search();
			}
		});
		panelSearch.add(Box.createHorizontalGlue());
		panelSearch.add(new JLabel("Repeat "));
		panelSearch.add(repeats = new JComboBox(new String[]{"Default", "Random" , "One song", "All song",}));
		repeats.setEditable(false);
		repeats.setFocusable(false);
		repeats.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				configure.repeat = repeats.getSelectedItem().toString();
			}
		});
		panelSearch.add(new JLabel("Sort "));
		panelSearch.add(sorts = new JComboBox(new String[]{"Album", "Artist", "Genre"}));
		sorts.setEditable(false);
		sorts.setFocusable(false);
		sorts.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				albums.clearSelection();
				configure.sort = sorts.getSelectedItem().toString();
				setAlbums();
			}
		});
		return panelSearch;
	}
	
	private JMenu initMenuMedia(){
		menuMedia = new JMenu("Media");
		JMenuItem itemSelectMedia;
		menuMedia.add(itemSelectMedia = new JMenuItem("Select media player..."));
		itemSelectMedia.setIcon(getImage("zing16.png"));
		itemSelectMedia.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				String folder = System.getenv().get("ProgramFiles");
				folder = (folder == null)? "." : folder;
				final String str = showOpen("Chooser media player", new File(folder), "");
				if (str == null)
					return;
				boolean exist = false;
				if (configure.mediaPlayers.contains(str)) {
					configure.defaultMediaPlayer = str;
					exist = true;
				}
				if (!exist) {
					configure.mediaPlayers.add(str);
					configure.defaultMediaPlayer = str;
					JCheckBoxMenuItem item = new JCheckBoxMenuItem(str);
					menuMedia.add(item);
					group.add(item);
					item.setSelected(true);
					item.addActionListener(new ActionListener() {
						@Override
						public void actionPerformed(ActionEvent arg0) {
							configure.defaultMediaPlayer = str;
						}
					});
				}

			}
		});
		menuMedia.addSeparator();
		group = new ButtonGroup();
		for (int i = 0; i < configure.mediaPlayers.size(); i++){
			final String media = configure.mediaPlayers.get(i);
			JCheckBoxMenuItem item = new JCheckBoxMenuItem(media);
			item.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent arg0) {
					configure.defaultMediaPlayer = media;
				}
			});
			if (media.equals(configure.defaultMediaPlayer)){
				item.setSelected(true);
			}
			group.add(item);
			menuMedia.add(item);
		}
		return menuMedia;
	}
	
	private String showSave(String title, File currentFolder, String fileSelected){
		chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
		chooser.setDialogTitle(title);
		chooser.setCurrentDirectory(currentFolder);
		chooser.setSelectedFile(new File(fileSelected));
		int ret = chooser.showSaveDialog(GoogleMusic.this);
		if(ret == JFileChooser.APPROVE_OPTION){
			configure.oldFolder = chooser.getCurrentDirectory().getAbsolutePath();
			return chooser.getSelectedFile().getAbsolutePath();
		}
		return null;
	}
	
	private String showOpen(String title, File currentFolder, String fileSelected){
		chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
		chooser.setDialogTitle(title);
		chooser.setCurrentDirectory(currentFolder);
		chooser.setSelectedFile(new File(fileSelected));
		int ret = chooser.showOpenDialog(GoogleMusic.this);
		if(ret == JFileChooser.APPROVE_OPTION){
			configure.oldFolder = chooser.getCurrentDirectory().getAbsolutePath();
			return chooser.getSelectedFile().getAbsolutePath();
		}
		return null;
	}
	
	public void setRange(int value){
		slider.setRange(value);
	}
	
	public void setMax(int value){
		slider.max = value;
	}
	
	public void setValue(int value){
		slider.setValue(value);
	}
	
	public void setIconStatus(boolean set){
		iconStatus.setVisible(set);
	}
	
	public void setPlay(){
		mediaPlay.setIcon(getImage("pause.png"));
	}
	
	public void setSortType(){
		sorts.setSelectedItem(configure.sort);
	}
	
	public static void main(String[] args) {
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				try {
					UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
					new GoogleMusic();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

}
